home *** CD-ROM | disk | FTP | other *** search
/ MacWorld UK 2000 March / MW_UK_2000_03.iso / Shareware World / Utilities / Text Processing / Alpha / Tcl / SystemCode / templates.tcl < prev    next >
Encoding:
Text File  |  1999-09-15  |  8.6 KB  |  284 lines  |  [TEXT/ALFA]

  1. ## -*-Tcl-*-
  2.  # ###################################################################
  3.  #  Vince's Additions - an extension package for Alpha
  4.  # 
  5.  #  FILE: "templates.tcl"
  6.  #                                    created: 27/7/97 {9:29:20 pm} 
  7.  #                                last update: 15/9/1999 {7:37:32 pm} 
  8.  #  Author: Vince Darley
  9.  #  E-mail: <vince@santafe.edu>
  10.  #    mail: 317 Paseo de Peralta, Santa Fe, NM 87501
  11.  #     www: <http://www.santafe.edu/~vince/>
  12.  #  
  13.  # Copyright (c) 1997-1999  Vince Darley, all rights reserved
  14.  # 
  15.  # Simple template insertion mechanism.  Can be easily overridden
  16.  # by a more sophisticated scheme providing more features, whilst
  17.  # still working simply if desired.  Call any of these 
  18.  # procs from the outside:
  19.  # 
  20.  #  elec::Insertion args  -- insert the given args
  21.  #  elec::CenterInsertion args -- insert, then center redraw
  22.  #  elec::Wrap left right -- wrap left and right about the selection
  23.  #  
  24.  #  ring::+ -- move to the next template stop
  25.  #  ring::- -- move to the previous template stop
  26.  #  
  27.  # Any piece of text given to the three 'elec::' procs has a template
  28.  # conversion done.  Text of the form '•blah•' is converted to a single
  29.  # bullet '•', with 'blah' attached to it internally.  
  30.  # 
  31.  # A more sophisticated template package, available separately, can
  32.  # prompt the user with 'blah' in useful ways, and creates a proper
  33.  # template ring.
  34.  # 
  35.  #  modified by  rev reason
  36.  #  -------- --- --- -----------
  37.  #  27/7/97  VMD 1.0 original
  38.  # ###################################################################
  39.  ##
  40.  
  41. alpha::flag electricTab 0.1.2 global help {
  42.     Enabling the 'Electric Tab' feature allows Alpha you to use
  43.     the procedures 'Indent or Next Stop' and 'Tab or Complete' as
  44.     any of your 'Special Keys' bindings.
  45.     
  46.     What these procedures do is change the behaviour of the Tab
  47.     key to depend upon the context.  In other words, hitting Tab
  48.     will not usually insert a Tab, rather it may indent the
  49.     current line, or move to the next Stop mark or complete the
  50.     current text,...
  51.     
  52.     Note that 'cmd-Tab' is one of the possible key-bindings
  53.     used to complete whatever you type.  If you use cmd-Tab as
  54.     a 'program switcher' in MacOS or other software, then you
  55.     obviously cannot use that keybinding in Alpha, since it
  56.     will be intercepted by the operating system.
  57. }
  58.  
  59. namespace eval elec {}
  60. namespace eval bind {}
  61. namespace eval ring {}
  62.  
  63. proc alpha::useElectricTemplates {} {}
  64.  
  65. if {${alpha::platform} == "alpha"} {
  66.     # The character inserted into the text to indicate 'stop marks': useful
  67.     # positions which you can jump between very quickly
  68.     newPref variable elecStopMarker "•"
  69. } else {
  70.     newPref variable elecStopMarker "ï"
  71. }
  72.  
  73.  
  74. ## 
  75.  # -------------------------------------------------------------------------
  76.  #     
  77.  #    "elec::_Insertion" --
  78.  #    
  79.  #  Insert a piece of text, padding on the left appropriately.  The text
  80.  #  should already be correctly indented within itself.
  81.  #     
  82.  #  Any piece of the text of the form '•blah•' is converted into a single
  83.  #  bullet.  A more advanced version of this procedure, available
  84.  #  separately, allows the use of '•blah•' to prompt the user either in the
  85.  #  window, or status line, and makes the template stops permanent entities
  86.  #  so you can cycle back and forth through a template 'ring'. 
  87.  # -------------------------------------------------------------------------
  88.  ##
  89. proc elec::_Insertion { center args } {
  90.     set text [join $args ""]
  91.     set pos [getPos]
  92.     regsub -all "\t" $text [text::Tab] text
  93.     if {[regexp "\[\n\r\]" $text]} {
  94.     regsub -all "\[\n\r\]" $text "\r[text::indentTo $pos]" text
  95.     }
  96.     if {[regexp "…" $text]} {
  97.     regsub -all "…" $text [text::halfTab] text
  98.     }
  99.     setMark
  100.     global elecStopMarker
  101.     if {![regexp "•" $text] || ([regexp {^([^•]*)••$} $text "" text])} {
  102.     insertText $text
  103.     if {$center} { centerRedraw }
  104.     } else {
  105.     regsub -all {•[^•]*•} $text $elecStopMarker text
  106.     insertText $text
  107.     goto $pos
  108.     if {$center} { centerRedraw }
  109.     # need to go to the first tab stop
  110.     ring::+
  111.     }
  112. }
  113.  
  114.  
  115. # ◊◊◊◊ possible tab key bindings ◊◊◊◊ #
  116. # note: Also provided by the base Alpha system, these overide when 
  117. # Univs Completions package is in use (these may be more intricate).
  118.  
  119. ## 
  120.  # -------------------------------------------------------------------------
  121.  #     
  122.  #    "bind::IndentOrNextstop" --
  123.  #    
  124.  #  Either insert a real tab if your mode hasn't defined its electricTab
  125.  #  variable, or jump to the next template stop (if we're mid-template), or
  126.  #  indent the current line correctly.
  127.  #     
  128.  #  If this proc doesn't seem to do the right thing.  Make sure you've got
  129.  #  'electricTab' set correctly in your preferences! 
  130.  # -------------------------------------------------------------------------
  131.  ##
  132. proc bind::IndentOrNextstop {{hard 0}} {
  133.     global electricTab
  134.     if {$hard || !$electricTab} {
  135.     insertActualTab 
  136.     } else {
  137.     if {![ring::+]} {bind::IndentLine}
  138.     }
  139. }
  140.  
  141. ## 
  142.  # -------------------------------------------------------------------------
  143.  #     
  144.  #    "bind::TabOrComplete" --
  145.  #    
  146.  #  Either insert a real tab if your mode hasn't defined its electricTab
  147.  #  variable, or invoke the completion mechanism, or indent the current
  148.  #  line correctly.
  149.  #     
  150.  #  If this proc doesn't seem to do the right thing.  Make sure you've got
  151.  #  'electricTab' set correctly in your preferences! 
  152.  # -------------------------------------------------------------------------
  153.  ##
  154. proc bind::TabOrComplete {{hard 0}} {
  155.     global electricTab
  156.     if {$hard || !$electricTab} {
  157.     insertActualTab 
  158.     } else {
  159.     bind::Completion
  160.     }
  161. }
  162.  
  163. proc ring::+ {} {
  164.     global elecStopMarker
  165.     set pos [getPos]
  166.     if {[pos::compare $pos == [maxPos]]} { return 0 }
  167.     set searchResult [lindex [search -s -n -f 1 -m 0 -i 1 -r 0 $elecStopMarker $pos] 0]
  168.     if {[string length $searchResult]} {
  169.     goto $searchResult
  170.     deleteChar
  171.     return 1
  172.     } else {
  173.     return 0
  174.     }
  175. }
  176.  
  177. proc ring::- {} {
  178.     global elecStopMarker
  179.     set pos [getPos]
  180.     if {[pos::compare $pos == [minPos]]} { return 0 }
  181.     set searchResult [lindex [search -s -n -f 0 -m 0 -i 1 -r 0 $elecStopMarker $pos] 0]
  182.     if {[string length $searchResult]} {
  183.     goto $searchResult
  184.     deleteChar
  185.     return 1
  186.     } else {
  187.     return 0
  188.     }
  189. }
  190.  
  191. # Removes all tab stops from the current selection (if there is one) 
  192. # or the current document, maintaining the cursor position in the 
  193. # latter case.
  194. proc ring::clear {} {
  195.     watchCursor
  196.     set pos [getPos]
  197.     global elecStopMarker
  198.     if {[pos::compare [set start $pos] == [set end [selEnd]]]} {
  199.     set start [minPos]
  200.     set end [maxPos]
  201.     set text1 [getText $start $pos]
  202.     set subs1 [regsub -all -- $elecStopMarker $text1 {} text1]
  203.     set text2 [getText $pos $end]
  204.     set subs2 [regsub -all -- $elecStopMarker $text2 {} text2]
  205.     if {($subs1 == 0) && ($subs2 == 0)} {return}
  206.     append text $text1 $text2
  207.     replaceText $start $end $text
  208.     goto [pos::math $pos - $subs1]
  209.     message "[expr {$subs1 + $subs2}] stops cleared"
  210.     } else {
  211.     set text [getText $start $end]
  212.     set subs3 [regsub -all -- $elecStopMarker $text {} text]
  213.     if {$subs3 == 0} {return}
  214.     replaceText $start $end $text
  215.     set end [getPos]
  216.     select $start $end
  217.     message "$subs3 stops cleared"
  218.     }
  219. }
  220. # indicates we're a very basic ring
  221. proc ring::type {} { return 0 }
  222. proc ring::nth {} {
  223.     message "ring::nth requires the Better Templates feature"
  224. }
  225.  
  226. ## 
  227.  # -------------------------------------------------------------------------
  228.  # 
  229.  # "elec::CenterInsertion" --
  230.  # 
  231.  #  Insert and then do a refresh.  Useful for large electric insertions.
  232.  # -------------------------------------------------------------------------
  233.  ##
  234. proc elec::CenterInsertion {args} {
  235.     eval elec::_Insertion 1 $args
  236. }
  237.  
  238. ## 
  239.  # -------------------------------------------------------------------------
  240.  # 
  241.  # "elec::Insertion" --
  242.  # 
  243.  #  Just insert the electric item
  244.  # -------------------------------------------------------------------------
  245.  ##
  246. proc elec::Insertion { args } {
  247.     eval elec::_Insertion 0 $args
  248. }
  249. proc elec::ReplaceText { start end args } {
  250.     deleteText $start $end 
  251.     eval elec::_Insertion 0 $args
  252. }
  253.  
  254. ## 
  255.  # -------------------------------------------------------------------------
  256.  #     
  257.  #    "elec::Wrap" --
  258.  #    
  259.  #  Currently doesn't deal with indentation -- the wrapper is supposed to
  260.  #  handle that.
  261.  #     
  262.  #  Returns 0/1 to indicate if there was a selection which this proc
  263.  #  wrapped. 
  264.  # -------------------------------------------------------------------------
  265.  ##
  266. proc elec::Wrap { left right {complete 0}} {
  267.     set pos [getPos]
  268.     set s [getSelect]
  269.     if {[string length $s]} {
  270.     deleteText $pos [selEnd]
  271.     elec::Insertion $left $s $right
  272.     return 1
  273.     } else {
  274.     elec::Insertion $left "••" $right
  275.     if {$complete} {
  276.         bind::Completion
  277.     }
  278.     return 0
  279.     }
  280. }
  281.  
  282.  
  283.  
  284.